﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using Missbot.Common;
using Missbot.Core.Base;
using Dolany.UtilityTool;
using Missbot.Model.MsgInfos;

namespace Missbot.AIModule.Gaming.ChessAgainst
{
    /// <summary>
    /// 对决引擎
    /// </summary>
    public partial class ChessEngine : ITransient
    {
        /// <summary>
        /// 当前回合用户
        /// </summary>
        public InstanceUser SelfUser { get; set; }

        /// <summary>
        /// 对手用户
        /// </summary>
        public InstanceUser AimUser { get; set; }

        /// <summary>
        /// 当前群组
        /// </summary>
        public InstanceGroup Group { get; set; }

        /// <summary>
        /// 消息通道
        /// </summary>
        private IMsgChannel Channel { get; set; }

        /// <summary>
        /// 效果列表
        /// </summary>
        private readonly List<ChessEffectModel> EffectsList = new();

        /// <summary>
        /// 棋盘
        /// </summary>
        private ChessEffectModel[] Chessborad;

        #region Svcs

        public ChessSvc ChessSvc { get; set; }
        public WaiterSvc WaiterSvc { get; set; }
        public ILogSvc ILogSvc { get; set; }

        #endregion

        private IEnumerable<int> AvailableNums
        {
            get
            {
                var list = new List<int>();
                for (var i = 0; i < Chessborad.Length; i++)
                {
                    if (!Chessborad[i].IsChecked)
                    {
                        list.Add(i + 1);
                    }
                }

                return list;
            }
        }

        public void Init(InstanceGroup Group, InstanceUser SelfUser, InstanceUser AimUser, IMsgChannel Channel)
        {
            this.SelfUser = SelfUser;
            this.AimUser = AimUser;
            this.Group = Group;
            this.Channel = Channel;

            var type = GetType();
            var methods = type.GetMethods();
            foreach (var method in methods)
            {
                if (!(method.GetCustomAttribute(typeof(ChessEffectAttribute)) is ChessEffectAttribute attr))
                {
                    continue;
                }

                EffectsList.Add(new ChessEffectModel
                {
                    Name = attr.Name,
                    Description = attr.Description,
                    Method = method.CreateDelegate(typeof(Action), this) as Action
                });
            }
        }

        public void GameStart()
        {
            try
            {
                Channel.Send(new InboxSession { Group = Group }, "对决即将开始，请双方做好准备！");
                Thread.Sleep(2000);
                InitChessBoard();

                for (var i = 0; i < 6; i++)
                {
                    ProceedTurn();
                    Thread.Sleep(1000);

                    (SelfUser, AimUser) = (AimUser, SelfUser);
                }

                Channel.Send(new InboxSession { Group = Group }, "对决结束！");
            }
            catch (Exception ex)
            {
                ILogSvc.LogError(ex);
                Channel.Send(new InboxSession { Group = Group }, "系统异常，游戏结束！");
            }

            ChessSvc.GameOver(this);
        }

        private void ProceedTurn()
        {
            var selectedNum = WaiterSvc.WaitForNum(new InboxSession
                                                   {
                                                       Group = Group,
                                                       User = SelfUser,
                                                       Channel = Channel
                                                   }, $"回合开始！请输入合适的数字来获取随机效果！\n{ChessBoardStr()}",
                                                   num => AvailableNums.Contains(num));

            if (!AvailableNums.Contains(selectedNum))
            {
                return;
            }

            var model = Chessborad[selectedNum - 1];

            Channel.Send(new InboxSession { Group = Group }, $"随机效果已生效：{model.Name}！\n{model.Description}");

            Thread.Sleep(1000);

            model.Method();
            model.IsChecked = true;

            Thread.Sleep(1000);
        }

        private void InitChessBoard()
        {
            Chessborad = Rander.RandSort(EffectsList.ToArray()).Take(9).ToArray();
        }

        private string ChessBoardStr()
        {
            var str = string.Empty;
            for (var i = 0; i < Chessborad.Length; i++)
            {
                var model = Chessborad[i];
                str += model.IsChecked ? model.Name : $"{(i + 1).ToString()}  ";
                str += (i + 1) % 3 == 0 ? "\n" : "  ";
            }

            return str;
        }
    }
}